package com.spukmk3me.impl.libgdx;

import com.spukmk3me.math.Matrix4f;
import com.badlogic.gdx.math.Matrix4;

public class LibgdxMatrix4fWrapper implements Matrix4f
{
	public LibgdxMatrix4fWrapper()
	{
		m_gdxMatrix = new Matrix4();
	}

	@Override
	public void copy( Matrix4f matrix )
	{
		m_gdxMatrix.set( ((LibgdxMatrix4fWrapper)matrix).m_gdxMatrix );
	}

	@Override
	// They don't have this function D:
	public void add( Matrix4f matrix )
	{
		float[] m1 = m_gdxMatrix.val;
		float[] m2 = matrix.getRawData();
		
		m1[ 0 ]  += m2[ 0 ];
		m1[ 1 ]  += m2[ 1 ];
		m1[ 2 ]  += m2[ 2 ];
		m1[ 3 ]  += m2[ 3 ];
		
		m1[ 4 ]  += m2[ 4 ];
		m1[ 5 ]  += m2[ 5 ];
		m1[ 6 ]  += m2[ 6 ];
		m1[ 7 ]  += m2[ 7 ];
		
		m1[ 8 ]  += m2[ 8 ];
		m1[ 9 ]  += m2[ 9 ];
		m1[ 10 ] += m2[ 10 ];
		m1[ 11 ] += m2[ 11 ];
		
		m1[ 12 ] += m2[ 12 ];
		m1[ 13 ] += m2[ 13 ];
		m1[ 14 ] += m2[ 14 ];
		m1[ 15 ] += m2[ 15 ];
	}

	@Override
	// They don't have this function D:
	public void mul( float n )
	{
		s( n, n, n );
	}

	@Override
	public void mul( Matrix4f matrix )
	{
	    System.arraycopy( matrix.getRawData(), 0, m_gdxMatrix.tmp, 0, 16 );
	    Matrix4.mul( m_gdxMatrix.tmp, m_gdxMatrix.val );
	    System.arraycopy( m_gdxMatrix.tmp, 0, m_gdxMatrix.val, 0, 16 );
	}
	
	@Override
    public void mul_inv( Matrix4f matrix )
    {
	    Matrix4.mul( m_gdxMatrix.val, matrix.getRawData() );
        m_gdxMatrix.mul( ((LibgdxMatrix4fWrapper)matrix).getGdxMatrix() );
    }

	@Override
	public void s( float x, float y, float z )
	{
		m_gdxMatrix.scale( x, y, z );
	}

	@Override
	public void t( float x, float y, float z )
	{
	    m_gdxMatrix.tmp[ 0 ]   = 1;
	    m_gdxMatrix.tmp[ 1 ]   = 0;
	    m_gdxMatrix.tmp[ 2 ]   = 0;
	    m_gdxMatrix.tmp[ 3 ]   = 0;
	    
	    m_gdxMatrix.tmp[ 4 ]   = 0;
	    m_gdxMatrix.tmp[ 5 ]   = 1;
	    m_gdxMatrix.tmp[ 6 ]   = 0;
	    m_gdxMatrix.tmp[ 7 ]   = 0;
	    
	    m_gdxMatrix.tmp[ 8 ]   = 0;
	    m_gdxMatrix.tmp[ 9 ]   = 0;
	    m_gdxMatrix.tmp[ 10 ]  = 1;
	    m_gdxMatrix.tmp[ 11 ]  = 0;
	    
	    m_gdxMatrix.tmp[ 12 ]  = x;
	    m_gdxMatrix.tmp[ 13 ]  = y;
	    m_gdxMatrix.tmp[ 14 ]  = z;
	    m_gdxMatrix.tmp[ 15 ]  = 1;

        Matrix4.mul( m_gdxMatrix.tmp, m_gdxMatrix.val );
        System.arraycopy( m_gdxMatrix.tmp, 0, m_gdxMatrix.val, 0, 16 );
	}

	@Override
	public void r( float x, float y, float z, float angle )
	{
		//m_gdxMatrix.rotate( x, y, z, (float)(angle * 180 / Math.PI) );
	}

	@Override
	public void invert()
	{
		m_gdxMatrix.inv();
	}

	@Override
	public float[] getRawData()
	{
		return m_gdxMatrix.val;
	}

	@Override
	public void setRawData( float[] data, int offset )
	{
	    float[] val = m_gdxMatrix.val;
	    
	    val[ 0 ]   = data[ offset++ ];
	    val[ 1 ]   = data[ offset++ ];
	    val[ 2 ]   = data[ offset++ ];
	    val[ 3 ]   = data[ offset++ ];
	    
	    val[ 4 ]   = data[ offset++ ];
	    val[ 5 ]   = data[ offset++ ];
	    val[ 6 ]   = data[ offset++ ];
	    val[ 7 ]   = data[ offset++ ];
	    
	    val[ 8 ]   = data[ offset++ ];
	    val[ 9 ]   = data[ offset++ ];
	    val[ 10 ]  = data[ offset++ ];
	    val[ 11 ]  = data[ offset++ ];
	    
	    val[ 12 ]  = data[ offset++ ];
	    val[ 13 ]  = data[ offset++ ];
	    val[ 14 ]  = data[ offset++ ];
	    val[ 15 ]  = data[ offset++ ];
	}

	@Override
	public void reset()
	{
		m_gdxMatrix.idt();
	}

	@Override
	public boolean hasTranslation()
	{
		float[] m = m_gdxMatrix.getValues();
		
		return (m[ 12 ] != 0f) || (m[ 13 ] != 0f) || (m[ 14 ] != 0f);
	}

	@Override
	public boolean hasRotation()
	{
		float[] m = m_gdxMatrix.getValues();
		
		return  (m[ 1 ] != 0f) || (m[ 2 ] != 0f) ||
                (m[ 4 ] != 0f) || (m[ 6 ] != 0f) ||
                (m[ 8 ] != 0f) || (m[ 9 ] != 0f);
	}

	@Override
	public boolean hasScaling()
	{
		float[] m = m_gdxMatrix.getValues();
		
		return (m[ 0 ] != 0f) || (m[ 5 ] != 0f) || (m[ 10 ] != 0f);
	}
	
	Matrix4 getGdxMatrix()
	{
		return m_gdxMatrix;
	}
	
	private Matrix4 m_gdxMatrix;
}
